#include <sstream>
#include <memory>
#include <algorithm>
#include <fstream>

#include <sys/reboot.h>

#include "config.hpp"
#include "dtu.hpp"
#include "sys_var.hpp"
#include "defines.hpp"
#include "uvlper.hpp"
#include "udp.hpp"
#include "base64.hpp"
#include "leds.hpp"
#include "dial.hpp"
#include "gps.hpp"
#include "devM.hpp"

#if ENABLE_MODBUS == 1 
    #include "modbus.hpp"
#endif
// ////////////////////////////////////////////////////////////////////////////////////////////////////
std::mutex  globeMutex;
dtu * globeDTU = nullptr;
std::unique_ptr< led > gLed;
/// 定义全局的设备重启计时器。如果这个计时器启动后，再计时完成后会调用操作系统重启函数
/// 重新启动。
CTimer m_restart_timer;
//////////////////////////////////////////////////////////////////////////////////////////////////////

dtu::dtu(): m_filter_lists( 10 ), m_is_dail_ready( false )
{
	// 读取系统配置文件，根据系统配置文件启动相关内容
	std::shared_ptr<CSysVar> pt_var = GetOrCreateSysVar( );
	globeDTU = this;
	if( pt_var ){
		// 𥘉始化自动启动
		init_auto_boot( pt_var );
		// 从设置数据中读取启动信息
		pt_var->GetValue( "/startMsg" , m_start_msg );
		// 读取自动重启信息 m_conn_flag
		int rst_time = 20;
		pt_var->GetValue( "/autoRestartTime" , rst_time  );
		
		//if( d < 100 ) d = 100;
		m_restart_intval = rst_time;
		__show_line_1( "%s AUTO RESTART TIME: %d s" , TRED , rst_time , TNORMAL );
		m_restart_timer( rst_time * 1000 );
		m_restart_timer.SetOwner( []{
    		__show_line_1( "%s%s%s" , TBLUE , "Reboot timer triggered." , TNORMAL );
			#if REBOOT_TIMER == 1
				sync();
				reboot( RB_AUTOBOOT );
			#endif
		});
#if ENABLE_WIFI == 1 
        	init_wifi();
#endif

#if ENABLE_PHY == 1 
        	init_phy();
#endif
		// 允许SIM卡热插拔
		//enable_simHotInsert();
		// 初始化GPS控制器
		CreateGPS();
        	// 初始化总事件循环器
        	CreateLooper();
		// 初始化LED 状态指示灯
		gLed = std::move( std::unique_ptr< led >( new led() ) );
		// 从设置数据中读取工作模式
		init_wkmod( pt_var );
		// 从设置数据中读取AT指令密码
		init_at_passwd( pt_var );
		// 读取SN
		pt_var->GetValue( "/SN" , m_sn );
		// 初始化串口设备表
		init_serial_port_tbl( pt_var );
		// 初始化串口设备 , 必须首先初始化串口设备。因为串口设备是DTU的核心部件，所有的其他
		// 部件都是围绕串口设备展开，所以串口是被必须作为DTU的龙头也是过滤器链条的最初一环
		init_serial         ( pt_var );
#if ENABLE_MODBUS ==  1
        	init_modbus         ( pt_var );
#endif
		// 初始化串口AT指令
		atInst *at = new atCom( atInst::at_serial , m_filter_lists[ 0 ].get() );
		at->addlist( m_filter_lists[ 0 ].get() );
		m_filter_lists[ 0 ]->push_back( at );
		// 初始化TCP
		if( init_tcp            ( pt_var ) == false )
			std::cout << TYELLOW << "[ CLOSED ]" << TNORMAL << std::endl;
		
		// 初始化UDP
		if( init_udp            ( pt_var ) == false ){
			std::cout << TYELLOW << "[ CLOSED ]" << TNORMAL << std::endl;
		}
		// 初始化网络状态监控模块
		init_net_demon();

		// 初始化AT指令模块
	    	init_at             ( pt_var );

		// 初始化HTTP透传接口
        	init_http           ( pt_var );

		// 初始化短信透传接口
		init_sms();
        	// 点亮工作LED灯
        	led::GetLed()->work( true );
		// 𥘉始化设备管理器
		//init_device_manager( );
		// 发送启动信息
		m_coms[ 1 ].ptserial->get()-> send( m_start_msg.length() , m_start_msg.c_str()   );
/*
#if ENABLE_CRYPTO
        	init_crypto         ( pt_var );
#endif
#if ENABLE_SSL
        	init_ssl            ( pt_var );
#endif
#if ENABLE_ZIP
		init_zip            ( pt_var );
#endif

#if ENABLE_MQTT
		init_mqtt           ( pt_var );
#endif
        */
    }
}

dtu::~dtu()
{
    //dtor
}

void dtu :: init_auto_boot( std::shared_ptr< CSysVar > ptvar )
{
	__show_line_1( "\n%s*************************************************\nStart auto boot\n********************************************%s" , TGREEN , TNORMAL);
	if( ptvar ){
		bool en = false;
		long t1 = 0;
		//int tmp_tm_hour;

		ptvar->GetValue( "/auto_boot/time", t1 );
		ptvar->GetValue( "/auto_boot/enable" , en );
		if( en ){
			m_auto_boot_timer( 500 ); // 500ms 检查一次时间,/etc/profile 中的时区参数需要，需要登录才能启动profile文件。
			m_auto_boot_timer.SetOwner( [ this , t1 ](){
				time_t 		t;				
				t = time( nullptr );
				struct tm* c_t = localtime( &t );
				if( c_t )
				{ // 成功拿到当前时钟，计算秒数
					if ((c_t->tm_hour + 8) >= 24)//超过1天
					{
						c_t->tm_hour = (c_t->tm_hour + 8 - 24);
					}
					else
					{
						c_t->tm_hour = c_t->tm_hour + 8;
					}
					long sec = ( c_t -> tm_hour )* 3600 + c_t->tm_min * 60 + c_t->tm_sec;//由于UTC时区问题，跟上海时间查8个小时故，小时+8
					__show_line_1("\n%s t1 = %ld , sec = %ld %s\n", TRED , t1 , sec , TNORMAL );
					if( t1 == sec )
					{
						__show_line_1("\n%s t1 = %ld , sec = %ld %s\n", TRED , t1 , sec , TNORMAL );
						__show_line_1("\n%s[[-- SYSTEM WILL RESTART --]]%s\n", TRED , TNORMAL );
						m_auto_boot_timer.Stop();
						system( "reboot" );
					}        
				}
				
				m_auto_boot_timer.Start( -1 , true );
			});
			// 启动计时器
			m_auto_boot_timer.Start( 500 , true );
		}
		
	}else{ // 没有办法拿到系统变量
		__show_line_1( "%sError , nullptr system variable.%s" , TRED, TNORMAL );
	}
}
/*
void dtu :: init_device_manager( )
{
	std::shared_ptr< CSysVar > ptvar = GetOrCreateSysVar();

	if( ptvar ){
		std::string svr;
		int port;

		ptvar->GetValue( "/devmanage/address" , svr );
		ptvar->GetValue( "/devmanage/port" , port );

		if( svr.empty() ){
			svr = "cloud.sn-iot.com";
			port = 10000;
		}
		try{
			filterList * ptlist = new filterList();
			atNet * at = new atNet( atInst::head , ptlist ) ;

			devManage * p_dev = new devManage( svr , port );

			ptlist->push_back( at );
			ptlist->push_back( p_dev );
			m_filter_lists[ 8 ] = std::shared_ptr< filterList >( ptlist );

		}catch( std::bad_alloc & e ){
			__show_line_1( "%sInit device manager interface fail%s", TRED , TNORMAL );
		}
		
	}else{ // 没有办法拿到系统变量
		__show_line_1( "%sError , nullptr system variable.%s" , TRED, TNORMAL );
	}
}
*/
void dtu::enable_simHotInsert()
{
	/*
	* 允许SIM卡热插拔。但是这个功能需要有硬件的支持，所以后续如果硬件支持了热插拔
	* 则可以使用这部分代码
	*/
	std::fstream fs("/dev/smd8" , std::ios::in | std::ios::out );
	if( fs.is_open() == true ){
		fs << "AT+QSIMDET=1,1\r\n";
		std::string str;
		usleep( 400000 );
		std::getline( fs , str );
		if( str.find( "OK" ) == std::string::npos ){
			std::cout << "Initialize SIM Card hot inserting fail." << std::endl;
		}

		fs.close();
	}
}

bool dtu::is_dail_ready()
{
	bool ret = false;
	FILE * fp = popen( "ifconfig" , "r");
	if( fp == nullptr ){
		__show_line_1("%s%s%s" , TRED , "Can not init network check command." , TNORMAL );
		return false;
	}
	char * data = (char *)malloc( 500 );
	if( data == nullptr ){
		__show_line_1( "%s%s%s" , TRED , "allocate memory fail" , TNORMAL );
		pclose( fp );
		return ret;
	}
	while( fgets( data , 499 , fp ) != nullptr ){
		std::string str =  data ;
		if( str.find( "rmnet_data0" ) != std::string::npos ){ // 说明拨号没有成功，网络没有建立
			ret = true;
			m_is_dail_ready = ret;
			break;
		}
		m_is_dail_ready = ret;
	}
	free( data );
	pclose( fp );
	return ret;
}

void dtu::init_net_demon()
{
	m_net_demon_timer( 10000 );             // 10s检查一次信号情况
	m_net_demon_timer.SetOwner([this]{
		
		bool flag = is_dail_ready();        // 检查拨号是否成功

		//__show_line_1( "%s net demon flag = %d%s" , TYELLOW , flag , TNORMAL );
		if( flag == false ){
			led::GetLed()->net( 0 );
			led::GetLed()->socka( false );
			led::GetLed()->socka( false );
			m_net_demon_timer.Start( 10000 , true );
			return;
		}
		// 检查信号类型
		ec20dial::sim_type  type = ec20dial::check_radio();
		switch ( type ) {
			case ec20dial::_2G: led::GetLed()->net( 2 ); break;
			case ec20dial::_3G: led::GetLed()->net( 3 ); break;
			case ec20dial::_4G: led::GetLed()->net( 4 ); break;
			case ec20dial::__NW_UNKNOWN:
			default:
				led::GetLed()->net( 0 );
				led::GetLed()->socka( false );
				led::GetLed()->socka( false );
			break;
		}

		m_net_demon_timer.Start( 10000 , true );
	});

	m_net_demon_timer.Start( 100 , true );
}

void dtu::init_wkmod( std::shared_ptr< CSysVar> ptval )
{
	if( ptval ){
		std::string str;
		ptval->GetValue( "/wkmod" , str );

		switch( hash_( str.c_str() )){
		case hash_compile_time( "NET" ):
		//m_wkmod = NET;
		break;
		case hash_compile_time( "HTTP" ):
		//m_wkmod = HTTPD;
		break;
		case hash_compile_time( "SMS" ):
		//m_wkmod = SMS;
		break;
		case hash_compile_time( "MQTT"):
		break;
		default:break;;
		//m_wkmod = NET;
		}
	}
}

dtu::err_code
dtu::RestartIntval( long itvl )
{
	std::shared_ptr< CSysVar > ptvar = GetOrCreateSysVar();
	if( ptvar ){
		m_restart_intval = itvl;
		ptvar->SetValue("/autoRestartTime" , itvl);
		return OK;
	}

	return ERR_CONF_OBJ;
}

dtu::err_code
dtu::set_wkmod( std::shared_ptr< CSysVar > ptval , const std::string& mod )
{
	if( ptval ){
		std::string str = mod.substr( mod.find( "\"") + 1 , mod.length() );
		str = str.substr( 0, str.find( "\"") );
		switch( hash_( str.c_str())){
		case hash_compile_time( "NET" ):
		//m_wkmod = NET;
		ptval->SetValue( "/wkmod" , mod );
		break;
		case hash_compile_time( "HTTPD" ):
		//m_wkmod = HTTPD;
		ptval->SetValue( "/wkmod" , mod );
		break;
		case hash_compile_time( "SMS" ):
		ptval->SetValue( "/wkmod" , mod );
		//m_wkmod = SMS;
		break;
		default:
		return ERR_WKMOD_NOT_SUPPORTED;
		}
	}else{
		return ERR_CONF_OBJ;
	}

	return OK;
}

void dtu :: init_at_passwd( std::shared_ptr< CSysVar> ptvar )
{
   	 ptvar->GetValue( "/at/passwd" , m_at_pswd );
}

dtu::err_code
dtu :: set_at_passwd( std::shared_ptr< CSysVar > ptvar , const std::string& pswd )
{
	if( ptvar ){
		m_at_pswd = pswd;
		ptvar->SetValue( "/at/passwd" , pswd );
		return OK;
	}

	return ERR_CONF_OBJ;
}

std::string dtu :: ATPswd()
{
    	return m_at_pswd;
}

dtu :: err_code
dtu :: ATPswd( const std::string& pswd )
{
	std::shared_ptr< CSysVar > ptvar = GetOrCreateSysVar();

	return set_at_passwd( ptvar , pswd );
}

dtu::err_code
dtu ::  WKMOD( const std::string& wkmod )
{
	std::shared_ptr< CSysVar > ptvar = GetOrCreateSysVar();

	return set_wkmod( ptvar , wkmod );
}

void dtu::init_serial_port_tbl() 
{
#if !defined( SERIAL_PORT )
#    error "Pls define serial hardware count."
#else
	std::stringstream ss;
	int count;
	std::shared_ptr< CSysVar > ptvar = GetOrCreateSysVar();
	if( ptvar ){
		ptvar->GetValue( "/serial/count" , count );
	}else{
		count = SERIAL_PORT;
	}
	// 添加调试串口

	stCOM item;
	item.name   = "/dev/ttyGS0";
	item.aliase = "com0";
	item.fd     = -1;
	m_coms.push_back( item );

	// 添加用户串口
	for( int i = 0; i < SERIAL_PORT ; i ++ ){
		ss << "/dev/ttyHS" << i;
		item.name = std::move(ss.str());
		ss.clear();

		ss << "com" << i + 1;
		item.aliase = std::move( ss.str() );
		item.fd = -1;

		m_coms.push_back( item );
	}
#endif
}

void dtu::init_serial_port_tbl( std::shared_ptr< CSysVar > ptvar ) 
{
#if !defined( SERIAL_PORT )
#    error "Pls define serial hardware count."
#else
	std::stringstream ss;
	int count;

	if( ptvar ){
		ptvar->GetValue( "/serial/count" , count );
	}else{
		count = SERIAL_PORT;
	}
	stCOM item;

	item.name   = "/dev/ttyGS0";
	item.aliase = "com0";
	item.fd     = -1;
	m_coms.push_back( item );
	for( int i = 0; i < SERIAL_PORT; i ++ ){
		ss << "/dev/ttyHS" << i;
		item.name = std::move(ss.str());
		ss.clear();

		ss << "com" << i;
		item.aliase = std::move( ss.str() );
		item.fd = -1;

		m_coms.push_back( item );
	}
#endif
}

dtu::err_code dtu::StartMsg( const std::string& msg )
{
	std::shared_ptr< CSysVar > ptvar = GetOrCreateSysVar();
	if( ptvar ){
		m_start_msg = msg;
		ptvar->SetValue( "/startMsg" , msg );
		return OK;
	}

	return ERR_CONF_OBJ;
}

std::string dtu::StartMsg( )
{
    	return m_start_msg;
}

#if ENABLE_MODBUS == 1 

void dtu::init_modbus(std::shared_ptr<CSysVar> ptvar ) 
{
	if( ptvar ){
		bool  en = false;
		//std::string   wkmod;

		ptvar->GetValue( "/modbus/enable" , en );

		if( en == true ){  // 功能已经开启
			try{
				std::shared_ptr<filterList> datalist( new filterList() );
				datalist->push_back( m_coms[ 1 ].ptserial.get() );

				modbus  * ptmodbus = new modbus( 500 , 5000 , filterIO::tail , datalist.get() );
				
				datalist->push_back( ptmodbus );
				
				m_coms[ 1 ].ptserial->addlist( datalist.get() );
				m_filter_lists[ 9 ] = datalist;
			}catch( std::bad_alloc& e ){
				__show_line_1( "%s%s%s" , TRED , "Allocate memory fail, Initialize modbus engine fail." , TNORMAL );
				abort();
			}catch( ... ){
				__show_line_1( "%s%s%s" , TRED , "Unknow error, Initialize modbus engine fail." , TNORMAL );
				abort();
			}
		
		}else{ // 功能没有开启
			std::cout << TNORMAL << "\tInitialize Modbus engine..." << TYELLOW << " [ CLOSED ]" << std::endl;
		}
	}else{
		__show_line_1( "%s%s%s" , TRED , "System variable object fail." , TNORMAL );
	}
}
#endif

void dtu::init_crypto(std::shared_ptr<CSysVar> ptvar ) 
{
}

void dtu::init_ssl(std::shared_ptr<CSysVar> ptvar ) 
{
}

void dtu::init_zip(std::shared_ptr<CSysVar> ptvar )
{
}


bool dtu::init_tcp(std::shared_ptr<CSysVar> ptvar )
{
	std::cout << TNORMAL << "\tInitializing TCP Socket(s)...";
	bool ret = false;
	try{
		std::string svr = "cloud.sn-iot.com" , path;
		int port = 10000;
		bool en = false , ssl = false;

		for( int i = 1; i < 5; i ++ ){
			std::string protocol;
			std::stringstream  ss;
			ss << "/net/socket/sock" << i << "/";
			path = ss.str();
			ptvar->GetValue( path + std::string( "protocol") , protocol);
			ptvar->GetValue( path + std::string("enable") , en );
			ptvar->GetValue( path + std::string("ssl/enable") , ssl );

			if( en && protocol == "TCP" && ssl == false ){
				std::cout << TNORMAL << "\n\t\tInitializing TCP Socket " << TGREEN << i << TNORMAL << "..." ;
				ptvar->GetValue( path + "server" , svr );
				ptvar->GetValue( path + "port" , port );
				tcp * pttcp = nullptr;
				if( i == 1 ){  // 第一条链条在创建串口的时候已经创建完成
					pttcp = new tcp( filterIO::tail , m_filter_lists[ 1 ].get() );
					m_filter_lists[ 1 ]->push_back( pttcp );
				}else{         // 其他链条需要在创建SOCKET 的时候进行创建
					std::shared_ptr<filterList> datalist( new filterList() );
					m_coms[ 1 ].ftbl[ i ] = datalist.get();
					datalist->push_back( m_coms[ 1 ].ptserial.get());
					m_coms[ 1 ].ptserial->addlist( datalist.get() );

					pttcp = new tcp( filterIO::tail , datalist.get() );
					
					// 在过滤器链记录中添加过滤器
					m_filter_lists[ i + 1 ] = datalist;
					m_filter_lists[ i + 1 ]->push_back( pttcp );
				}
				pttcp->Index( i );
				pttcp->connect( svr , port );

				stNet netitem;
				std::vector< stNet > ::iterator it;

				it = std::find_if( m_nets.begin() , m_nets.end() , [ i ]( const stNet& item )->bool{
					return i == item.index;
				} );
				if( it != m_nets.end() )
					m_nets.erase( it );

				netitem.index = i;
				netitem.serial_id = -1;
				netitem.locked = false;
				netitem.type = SOCKET;
				netitem.pt_socket.reset( pttcp );

				m_nets.push_back( netitem );

				ret = true;
			}
		}

	}catch( std::bad_alloc& e ){
		std::cout << TRED << "[ FAIL ]" << TNORMAL << std::endl;
		__show_line_1( "%s%s%s" , TRED , "Can not alloc memory." , TNORMAL );
		abort();
	}

	return ret;
}

bool dtu::init_udp(std::shared_ptr<CSysVar> ptvar )
{
	bool ret = false;
	try{
		std::string       svr = "cloud.sn-iot.com";
		int               port = 10001;
		std::string       protocol , path;
		std::stringstream ss;
		bool              en = false;
		std::cout << TNORMAL << "\tInitializing UDP Socket(s)...";
        	for( int i = 1; i < 5; i ++ ){
			ss << "/net/socket/sock" << i << "/";
			path = ss.str();

			ptvar -> GetValue( path + "protocol" , protocol );
            		if( protocol == "UDP" ){
				ptvar -> GetValue( path + "enable" , en );
				if( en ){
					ptvar->GetValue( path + "server" , svr );
					ptvar->GetValue( path + "port" , port );
					udp * ptudp = nullptr;
					try{
						std::cout << TNORMAL << "\t\tInitializing UDP Socket " << TGREEN << i << TNORMAL << "..." ;
									stNet netitem;
						if( i == 1 ){  // 第一条链条在创建串口的时候已经创建完成
							ptudp = new udp( filterIO::tail , m_filter_lists[ 1 ].get() );
							m_filter_lists[ 1 ]->push_back( ptudp );
						}else{         // 其他链条需要在创建SOCKET 的时候进行创建
							std::shared_ptr<filterList> datalist( new filterList() );
							m_coms[ 1 ].ftbl[ i ] = datalist.get();
							datalist->push_back( m_coms[ 1 ].ptserial.get());
							m_coms[ 1 ].ptserial->addlist( datalist.get() );
							ptudp = new udp( filterIO::tail , datalist.get() );
							// 在过滤器链记录中添加过滤器
							m_filter_lists[ i + 1 ] = datalist;
							m_filter_lists[ i + 1 ]->push_back( ptudp );
						}

						// 仅仅解析域名生成目标地址
						ptudp->connect( svr , port );

						std::vector< stNet > ::iterator it;

						it = std::find_if( m_nets.begin() , m_nets.end() , [i ]( const stNet& item )->bool{
							return i == item.index;
						} );
						if( it != m_nets.end() )
							m_nets.erase( it );

						netitem.index = i;
						netitem.serial_id = -1;
						netitem.locked = false;
						netitem.type = SOCKET;
						netitem.pt_socket.reset( ptudp );
						ptudp->Index( i );
						m_nets.push_back( netitem );

						std::cout << TGREEN << "[ OK ]" << TNORMAL << std::endl;
						ret = true;
					}catch( filterIO::err_code e ){
						std::cout << TRED << "[ FAIL ]" << TNORMAL << std::endl;
						std::cerr << TRED << "Error Initialize UDP Client" << TNORMAL << std::endl;
						abort();
					}
                		}
            		}
            		ss.clear();
            		ss.str("");

        	}
    	}catch( std::bad_alloc& e ){
		std::cout << TRED << "[ FAIL ]" << TNORMAL << std::endl;
		__show_line_1("%s%s%s" , TRED , "Can't Allocate  Memory" , TNORMAL );
		abort();
    	}

    	return ret;
}

void dtu::init_http(std::shared_ptr<CSysVar> ptvar )
{
	bool en = false;
	if( ptvar ){
		ptvar->GetValue( "/http/enable" , en );
			std::cout << TNORMAL << "\tInitializing HTTP Module..." << TNORMAL ;
		if( en ){
			std::string svr , url , head;
			int port = 0;
			bool ssl = false;

			ptvar->GetValue( "/http/server" , svr  );
			ptvar->GetValue( "/http/port" ,   port );
			ptvar->GetValue( "/http/url"  ,   url  );
			ptvar->GetValue( "/http/head" ,   head );
			ptvar->GetValue( "/http/ssl",     ssl  );
			char * buff = ( char *)malloc( head.length() );
			if( buff == nullptr ){
				std::cout << TRED << "" << TNORMAL << std::endl;
				std::cerr << TRED << "" << TNORMAL << std::endl;
				abort();
			}
			size_t s = Base64Decode( head , buff );
			if( s <= 0 ){
				std::cout << TRED << "" << TNORMAL << std::endl;
				std::cerr << TRED << "" << TNORMAL << std::endl;
				free( buff );
			}
			buff[ s ] = 0;
			head = buff;
			free( buff );

			try{
				std::shared_ptr<filterList> datalist( new filterList() );
				m_coms[ 1 ].ftbl[ 5 ] = datalist.get();                       // 在串口设备中添加入口
				datalist->push_back( m_coms[ 1 ].ptserial.get());             // 将串口设备出口和链表链接起来
				m_coms[ 1 ].ptserial->addlist( datalist.get() );
				http * pthttp = new http( datalist.get() );                   // 创建接口
				// 初始化相关参数
				pthttp->server( svr );                pthttp->port( port );
				pthttp->url( url );                	  pthttp->head( head );
				pthttp->ssl( ssl );

				datalist->push_back( pthttp );                                // 链接HTTP服务和串口服务

				m_filter_lists[ 6 ] = datalist;                               // 在过滤器链挂管理记录中添加过滤器

				std::cout << TGREEN << "[ OK ]" << TNORMAL << std::endl;
			}catch( std::bad_alloc& e ){
				std::cout << TRED << "[ FAIL ]" << TNORMAL << std::endl;
				__show_line_1("%s%s%s" , TRED , "Can't Allocate  Memory" , TNORMAL );
				abort();
			}
		}else{
			std::cout << TYELLOW << " [  CLOSED ]" << TNORMAL << std::endl;
		}
	}else{
		std::cout << TRED << "[ FAIL ]" << TNORMAL << std::endl;
		abort();
	}
}
#if ENABLE_MQTT == 1
void dtu::init_mqtt(std::shared_ptr<CSysVar> ptvar )
{

}
#endif

void dtu :: init_sms()
{
	bool en = false , at_enable = false;
	std::shared_ptr< CSysVar > ptvar = GetOrCreateSysVar();
    	if( ptvar ){
        	ptvar->GetValue( "/sms/enable" , en );
		ptvar->GetValue( "/sms/at_enable" , at_enable );

        	if( en && at_enable ){
            		try{
               			 std::shared_ptr<filterList> datalist( new filterList() );
				// 创建短信AT指令对象
		   		atSMS  * atPtr = new atSMS( atInst::head , datalist.get() );
				m_ptAtSMS.reset( atPtr );
				// 创建短信过滤器对象
				smsio * ptsms = new smsio( filterIO::tail , datalist.get() );   // 创建接口
				// 设置过滤器头为AT指令过滤器
		   		datalist->push_back( atPtr );
				// 设置过滤尾为短信过滤器
                		datalist->push_back( ptsms );                                   // 连接 SMS 服务和 AT 指令服务

                		m_filter_lists[ 7 ] = datalist;                                 // 在过滤器链挂管理记录中添加过滤器
				std::cout << TNORMAL << "\tInitializing SMS AT Module..." << TNORMAL ;
                		std::cout << TGREEN << "[ OK ]" << TNORMAL << std::endl;
            		}catch( std::bad_alloc& e ){
				std::cout << TNORMAL << "\tInitializing SMS AT Module..." << TNORMAL ;
                		std::cout << TRED << "[ FAIL ]" << TNORMAL << std::endl;
                		__show_line_1("%s%s%s" , TRED , "Can't Allocate  Memory" , TNORMAL );
                		abort();
            		}
        	}else if( en ){  // 只初始化短信接口，不初始化短信AT指令
			std::cout << TNORMAL << "\tInitializing SMS Module..." << TNORMAL ;
			sms * ptSMS = new sms();
			ptSMS->OnMsg([this](const std::string& from , const char * d , size_t l , sms::sms_type type ){});
			ptSMS->OnSend( [ this ]( sms::err_code  e ){});
			ptSMS->OnOpen([ this ]( ){ });
			ptSMS->OnClose([ this ]{});
			std::cout << TGREEN << "[ OK ]" << TNORMAL << std::endl;
		}else{
			std::cout << TNORMAL << "\tInitializing SMS ..." << TYELLOW << " [ CLOSED ] " << TNORMAL << std::endl;
		}
    	}else{
		std::cout << TRED << " [ FAIL ]" << TNORMAL << std::endl;
		abort();
    	}
}

void dtu :: init_at( std::shared_ptr< CSysVar> ptvar ) 
{
    // 初始化网络AT指令/*
//郑州鼎为关闭网络AT指令代码	
/*
        bool en = true
	if(ptvar)
		ptvar->GetValue("/at/enable_net", en);
		if(!en) return;
*/
	for( size_t i = 0; i < m_nets.size(); i ++ ){
		 // 初始化过滤器链
		filterList * datalist = new filterList() ;
		 // 初始化AT指令解释执行器
		 atNet * ptat = new atNet( atInst::head , datalist );
		 // 搭接数据链
		 datalist->push_back( ptat );
		 datalist->push_back( m_nets[ i ].pt_socket.get() );
		 m_nets[ i ].pt_socket->addlist( datalist );
	}
}

void dtu::init_serial( std::shared_ptr< CSysVar> ptvar )
{
    // 初始化串口0, 控制串口用来操作AT指令

	try{
		std::cout << "\tStart AT Command serial port ..." ;
		init_serial_0( ptvar );
		std::cout << TGREEN << "[ OK ]" << TNORMAL << std::endl;
	}catch( err_code ){
		std::cout << TRED << "[ FAIL ]" << TNORMAL << "Initialize AT Command port fail." << std::endl;
		//StartRebootTimer();
		abort();
	}
	// 初始化串口1
	try{
		std::cout << "\tInitializing Data Serial Port...";
		init_serial_1( ptvar );
	}catch( err_code e ){
		abort();
	}
	// 初始化串口2
	//init_serial_2( ptvar );
}

void dtu::init_serial_0(std::shared_ptr< CSysVar > ptval ) 
{
	if( ptval ){
		bool en = false , has = false;

		ptval -> GetValue( "/serial/com0_en" ,   en );
		ptval -> GetValue( "/serial/has_com0" ,  has );      // 硬件是否有这个串口

		if( en && has ){
		try{
			std::shared_ptr<filterList> atlist( new filterList() );
					/** 这个部分的内容用来使用GS0串口进行AT指令通讯，正式产品没有这个功能
			m_coms[ 0 ].ptserial.reset( new serialIO( "com0" , filterIO::head , atlist.get() ) );
			m_coms[ 0 ].ptserial->pack( serialIO :: pack_mtd::NONE , 100 , 1024 );
			atlist->push_back( m_coms[ 0 ].ptserial.get() );
					*/
			m_filter_lists[0] = atlist ;
		}catch( ... ){
			throw ERR_INIT_SERIAL_0;
		}
		}
	}else{
		throw ERR_CONF_OBJ;
	}
}

void dtu::init_serial_1( std::shared_ptr< CSysVar > ptval )
{
	if( ptval ){
		bool en = false , has = false;

		ptval -> GetValue( "/serial/com1_en" ,   en );
		ptval -> GetValue( "/serial/has_com1" ,  has );      // 硬件是否有这个串口

		if( en && has ){
			try{
				std::shared_ptr<filterList> datalist( new filterList() );
				m_filter_lists[1] = datalist ;
				m_coms[ 1 ].ptserial.reset( new serialIO( "com1" , filterIO::head , datalist.get() ) );
				
				// 添加数据链头
				datalist->push_back( m_coms[ 1 ].ptserial.get() );
				//  AT 指令过滤器链表中添加串口1
				m_filter_lists[0]->push_back( m_coms[ 1 ].ptserial.get() );
				// 将AT指令添加到
				m_coms[ 1 ].ptserial->addlist( m_filter_lists[0].get() );
						
				std::cout << TGREEN << "[ OK ]" << TNORMAL << std::endl;
			}catch( ... ){
				std::cout << TRED << "[ FAIL ]" << TNORMAL << std::endl;
				throw ERR_INIT_SERIAL_1;
			}
		}else{
			std::cout << TYELLOW << "[ CLOSED ]" << TNORMAL << std::endl;
		}
	}else{
		std::cout << TRED << "[ FAIL ]" << TNORMAL <<  std::endl;
		throw ERR_CONF_OBJ;
	}
}

void dtu::init_serial_2( std::shared_ptr< CSysVar > ptval )
{
	if( ptval ){
		bool en = false , has = false;

		ptval -> GetValue( "/serial/com2_en" ,   en );
		ptval -> GetValue( "/serial/has_com2" ,  has );      // 硬件是否有这个串口

		if( en && has ){
			try{
				m_coms[ 2 ].ptserial.reset( new serialIO( "com2" , filterIO::head , nullptr ) );
			}catch( ... ){
				throw ERR_INIT_SERIAL_2;
			}
		}
	}else{
		throw ERR_CONF_OBJ;
	}
}

void dtu :: Run()
{
}

bool dtu :: Link( int index )
{
	bool ret = false;
	std::vector< stNet > :: iterator it;
	it = std::find_if( m_nets.begin() , m_nets.end() , [ this , index ]( const stNet& item )->bool{
		return index == item.index;
	});

	if( it != m_nets.end() ){
		if( it->pt_socket ){
			tcp * p = (tcp*)(it->pt_socket.get());
			if( p )
				ret = p ->IsConnected();
		}
	}

	return ret;
}
#if ENABLE_WIFI == 1 
void dtu :: init_wifi()
{
	std::shared_ptr< CSysVar > ptvar = GetOrCreateSysVar();

	if( ptvar ){
		std::string  ssid , pswd;
		bool en = false;
		ptvar->GetValue( "/wifi/enable" , en );
		if( en ){
			ql_wifi_enable();
		}else{
			ql_wifi_disable();
		}
	}else{
		ql_wifi_disable();
	}
}
#endif

#if ENABLE_PHY == 1 
int dtu :: init_phy( )
{
	std::shared_ptr< CSysVar > ptvar = GetOrCreateSysVar();
	if( ptvar ){
		bool en = false;
		ptvar->GetValue( "/phyen" , en );
		if( en == true ){// 配置有线网络为自动适配
			if(ql_sgmii_autoneg_set((ql_sgmii_autoneg_e)1) ){
				printf("\nset autoneg failure");
				return -1;
			}
			if(ql_sgmii_enable()) {// 启动以太网络
				printf("\nEnable SGMII Module failure");
				return -2;
			}
		}else{// 禁止以太网络
			ql_sgmii_disable();
		}
	}
	return 0;
}
#endif

/**
 */
std::string dtu :: GetIMEI()
{
	std::string ret;

	return ret;
}
/**
 */
std::string dtu :: GetICCID()
{
	std::string ret;

	return ret;
}

int dtu :: GetErrorCode()
{
	int ret = 0;

	return ret;
}
// ====================================================================================================
dtu* GetOrCreateDTU()
{
	dtu * ret = nullptr;

	if( globeDTU != nullptr )   ret = globeDTU;
	else{
		try{
			ret = new dtu();
		}catch( std::bad_alloc& e ){
			std::cout << TRED << "create dtu fail" << TNORMAL << std::endl;
			ret = nullptr;

			if( globeDTU ){
				delete globeDTU;       
				globeDTU = ret;
			}
			abort();
		}catch( ... ){
			std::cout << TRED << "Init dtu fail." << TNORMAL << std::endl;
			globeDTU = nullptr;
			ret = globeDTU;
		}
	}
	return ret;
}

void StopRebootTimer()
{
#if REBOOT_TIMER == 1
    m_restart_timer.Stop();
	
	__show_line_1( "%s%s%s" , TBLUE , "Reboot timer stopped" , TNORMAL );
#endif
}
/**
 * @brief 启动设备重启超时计时器
 */
void StartRebootTimer()
{
#if REBOOT_TIMER == 1
	m_restart_timer.Start( -1 , true );

    __show_line_1( "%s%s timer tick = %ld %s" , TBLUE , "Reboot timer started" , m_restart_timer(), TNORMAL );
#endif
}

std::string GetDeviceType()
{
#if DEVICE_TYPE == 0 
    	return std::string("LTE810");
#elif DEVICE_TYPE == 1
    	return std::string("LTE820");
#elif DEVICE_TYPE == 2 
    	return std::string("LTE810-G");
#endif
}